#ifndef __APP_XMODE_H__
#define __APP_XMODE_H__
#include <stdint.h>
#include "bootloader.h"
/*
SOH              0x01          //Xmodem数据头
STX              0x02           //1K-Xmodem数据头
EOT              0x04           //发送结束
ACK             0x06           //认可响应
NAK             0x15           //不认可响应
CAN             0x18           //撤销传送
CTRLZ         0x1A          //填充数据包
*/
typedef enum
{
    ERROR = 0,       ///< 错误
    SUCCESS = !ERROR ///< 成功
} ErrorStatus;
#ifndef FALSE
#define FALSE (0)
#endif

#ifndef TRUE
#define TRUE (1)
#endif
#define CHECK_DEV 0xFA
#define CHECK_DEV_ACK 0xFB
#define XIP_REMAP_ADDR 0x10000000

#define SOH 0x01 // 上位机告诉下位机正常传输 128Bte
#define STX 0x02 // 上位机告诉下位机正常传输 1024Bte
#define EOT 0x04 // 上位机告诉下位机传输全部完成
#define ACK 0x06 // 下位机应答本帧接收成功
#define NAK 0x15 // 下位机应答本帧接收失败让上位机重新发送该帧
#define CAN 0x18 // 上位机取消发送
#define CRCX 'C' // 下位机请求建立连接

#define CMD_XMODE_START "XMODE START"
#define C_CMD_XMODE_START_SIZE (sizeof(CMD_XMODE_START) - 1)

#define EXFLASH_PAGE_SIZE 0x1000

typedef enum __boot_loader_type__
{
    BL_TYPE_UpdApp = 0,

} BL_type;
typedef enum SYS_RUN_Sta_Enum
{
    C_Xmode_Sta_None = 0,
    C_Xmode_Sta_End,             // 结束  该值必须小于"启动"值
    C_Xmode_Sta_Start,           // 启动
    C_Xmode_Sta_CRCX,            // 开始建立连接	发'C'
    C_Xmode_Sta_Waite,           // 等待
    C_Xmode_Sta_TmrOver,         // 超时
    C_Xmode_Sta_SingFram_RxSucc, // 单帧接收成功
    C_Xmode_Sta_ChkErr,          // 校验失败
    C_Xmode_Sta_RxFinish,        // 全部接收完成

} SYS_Sta;
#define C_Xmdm_SOH_Frm_DataSize 128
#define C_Xmdm_STX_Frm_DataSize 1024
#pragma pack(1)
typedef struct
{
    uint8_t Cmd;
    uint8_t PackNum;     // 包序号
    uint8_t PackNumSupp; // 包序号补码
    uint8_t Data[C_Xmdm_STX_Frm_DataSize + 2];
} XmodeFram_Struct;

#pragma pack(4)
#define C_Xmdm_STX_Size sizeof(XmodeFram_Struct)
#define C_Xmdm_SOH_Size (C_Xmdm_STX_Size - C_Xmdm_STX_Frm_DataSize + C_Xmdm_SOH_Frm_DataSize)
#pragma pack(1)
/* 应答包结构 */
typedef struct
{
    uint8_t stx;  // 数据头
    uint16_t sum; // 校验和
    uint8_t len;  // 数据长度
    uint8_t cmd;
    uint8_t ret;
    uint8_t dataBuf[]; // 数据域长度不定
} T_FirmwareMsg_Struct;
#pragma pack(4)

#define C_RetryNum_Max 5   // 建立连接失败上限
#define C_ChkErrNum_Max 10 // 连续校验失败上限

#pragma pack(1)
typedef struct
{
    uint8_t RunSta;             // 当前状态
    uint8_t RetryCmd;           // 重发命令
    uint8_t RetryNum : 4;       // 建立连接次数
    uint8_t ChkErrNum : 4;      // 连续校验错误次数
    uint8_t WtFlashPackNum;     // 写入FLASHE的包编号(SIZE:128byte)
    uint16_t WtExFlashPageAdd;  // 满4K 写一次 EXFLASHE
    uint32_t WtExFlashAdd;      // 写入EXFLASHE的当前地址 就是从PC获取的 C_Xmdm_SOH_Frm_DataSize字节接下来需要存储到哪里去的地址
    uint32_t ReceiveCodeSize;   // 固件大小
    uint32_t WtExFlashStartAdd; // 写入EXFLASHE的起始地址
    uint32_t FirmwareSize;      // 固件大小
    uint32_t tick;
    uint32_t DelayTime;
    XmodeFram_Struct Fram;
} XmodeRxMsg_Struct;
#pragma pack(4)

void AppXmode(void);
void Xmode_Run_Sta_bp(void);
void Xmode_Msg_Init(void);
void Xmode_CRCX_Por(void);
void Xmode_Retry_Por(void);
void Xmode_ChkErr_Por(void);
void Xmode_RxFinish_Por(void);

int Xmode_Calcrc(uint8_t *ptr, int count);
uint8_t Xmode_check(uint8_t *buf);
void Xmode_Send_buff(unsigned char *buff, uint16_t size);
void Xmode_Analytic(void);

typedef enum err_Sta_Enum
{
    C_Err_None = 0,
    C_LockMode_Err, // 设备型号不同
    C_HW_Err,       // 硬件版本不同
    C_FW_Same,      // 软件版本相同
    C_Err_Timeout,  // 超时
    C_upding,       // 升级中
    C_updsucc,      // 升级成功
    C_WaitConnet,   // 等待连接
    C_upd_crc_err,  // 升级失败CRC err
} err_Sta;

typedef enum SYS_RUN_TXSta_Enum
{
    C_XmodeTx_Sta_None = 0,
    C_XmodeTx_Sta_WaiteConnet,            // 等待连接
    C_XmodeTx_Sta_End,                    // 结束  该值必须小于"启动"值
    C_XmodeTx_Sta_Start,                  // 启动
    C_XmodeTx_Sta_CheckDevInfor,          // 校验设置信息
    C_XmodeTx_Sta_CheckDevInfor_WaiteAck, //
    C_XmodeTx_Sta_WaiteRx,                // 等待接收
    C_XmodeTx_Sta_SingFram_RxSucc,        // 单帧接收成功
    C_XmodeTx_Sta_SingFram_RxErr,         // 单帧接收失败
    C_XmodeTx_Sta_TmrOver,                // 超时
    C_XmodeTx_Sta_TxFinish,               // 全部发送完成

} XmodeTx_Sta;

#pragma pack(1)
typedef struct
{
    uint8_t RunSta;        // 当前状态
    uint8_t RetryNum : 4;  // 建立连接次数
    uint8_t ChkErrNum : 4; // 连续校验错误次数
    uint32_t CurrPackNum;  // 当前编号
    uint32_t PackNums;     // 总编号
    uint32_t tick;
    uint32_t DelayTime;
    XmodeFram_Struct Fram;
} T_XmodeTxMsg_Struct;
#pragma pack(4)

void XmodeTx_Analytic(void);
void XmodeTx_Run_Sta_bp(void);
void AppXmodeTx(void);
extern uint32_t UpdSuccNum;
extern uint32_t StartTime;

extern void Oled_Display_UpdfWInfor(uint8_t *ver);
extern ErrorStatus AppCode_Check(uint32_t add, uint32_t len);
extern int Flash_Write(uint32_t iAddress, uint8_t *buf, uint32_t iNbrToWrite);
extern void Flash_Read(uint32_t add, uint8_t *buf, uint16_t len);
#endif /* __APP_XMODE_H__ */
